import { JSONParse } from '@/utils';
import { addEdit } from '../../hooks/component.hook';

// * 拖拽到编辑区域里
export const dragHandle = async (e, parentId) => {
	e.preventDefault();
	// 子元素的 drop 事件
	if (parentId) e.stopPropagation();
	try {
		// 获取拖拽数据
		const drayDataString = e?.dataTransfer?.getData('ChartData');
		if (!drayDataString) return;
		// 修改状态
		$store.chart.setEditCanvas('isCreate', false);
		// 添加进编辑区
		addEdit({ ...JSONParse(drayDataString), parentId }, e);
	} catch (error) {
		console.log(error);
		msgWarning(`图表正在研发中, 敬请期待...`);
	}
};

// * 进入拖拽区域
export const dragoverHandle = (e) => {
	e.preventDefault();
	// 子元素的 drop 事件
	e.stopPropagation();
	if (e.dataTransfer) e.dataTransfer.dropEffect = 'copy';
};

// * 不拦截默认行为点击
export const mousedownHandleUnStop = (e, item) => {
	if (item) {
		$store.chart.setTargetSelectChart(item.id);
		return;
	}
	$store.chart.setTargetSelectChart(undefined);
};

// * 框选
export const mousedownBoxSelect = (e) => {
	if (e.which == 2) return;
	// 按下空格
	if ($store.chart.KeyboardActive.space) return;

	mousedownHandleUnStop(e);

	// 记录点击初始位置
	const startOffsetX = e.offsetX;
	const startOffsetY = e.offsetY;
	const startScreenX = e.screenX;
	const startScreenY = e.screenY;

	// 记录缩放
	const scale = $store.chart.editCanvas.scale;

	$store.chart.setMousePosition(undefined, undefined, startOffsetX, startOffsetY);

	// 移动框选
	const mousemove = throttle((moveEvent) => {
		// 取消当前选中
		$store.chart.setTargetSelectChart();
		$store.chart.setEditCanvas('isSelect', true);

		// 这里先把相对值算好，不然组件无法获取 startScreenX 和 startScreenY 的值
		const currX = startOffsetX + moveEvent.screenX - startScreenX;
		const currY = startOffsetY + moveEvent.screenY - startScreenY;
		$store.chart.setMousePosition(currX, currY);

		// 计算框选的左上角和右下角
		const selectAttr = {
			// 左上角
			x1: 0,
			y1: 0,
			// 右下角
			x2: 0,
			y2: 0
		};
		if (currX > startOffsetX && currY > startOffsetY) {
			// 右下方向
			selectAttr.x1 = startOffsetX;
			selectAttr.y1 = startOffsetY;
			selectAttr.x2 = Math.round(startOffsetX + (moveEvent.screenX - startScreenX) / scale);
			selectAttr.y2 = Math.round(startOffsetY + (moveEvent.screenY - startScreenY) / scale);
		} else if (currX > startOffsetX && currY < startOffsetY) {
			// 右上方向
			selectAttr.x1 = startOffsetX;
			selectAttr.y1 = Math.round(startOffsetY - (startScreenY - moveEvent.screenY) / scale);
			selectAttr.x2 = Math.round(startOffsetX + (moveEvent.screenX - startScreenX) / scale);
			selectAttr.y2 = startOffsetY;
		} else if (currX < startOffsetX && currY > startOffsetY) {
			selectAttr.x1 = Math.round(startOffsetX - (startScreenX - moveEvent.screenX) / scale);
			selectAttr.y1 = startOffsetY;
			selectAttr.x2 = startOffsetX;
			selectAttr.y2 = Math.round(startOffsetY + (moveEvent.screenY - startScreenY) / scale);
			// 左下方向
		} else {
			// 左上方向
			selectAttr.x1 = Math.round(startOffsetX - (startScreenX - moveEvent.screenX) / scale);
			selectAttr.y1 = Math.round(startOffsetY - (startScreenY - moveEvent.screenY) / scale);
			selectAttr.x2 = startOffsetX;
			selectAttr.y2 = startOffsetY;
		}

		// 遍历组件
		$store.chart.componentList.forEach((item) => {
			// 未选中的，没有父类的组件
			if (!$store.chart.targetChart.selectId.includes(item.id) && !item.parentId) {
				const { x, y, w, h } = item.orgConfig.attr;
				const targetAttr = {
					// 左上角
					x1: x,
					y1: y,
					// 右下角
					x2: x + w,
					y2: y + h
				};
				// 全包含则选中
				if (
					targetAttr.x1 - selectAttr.x1 >= 0 &&
					targetAttr.y1 - selectAttr.y1 >= 0 &&
					targetAttr.x2 - selectAttr.x2 <= 0 &&
					targetAttr.y2 - selectAttr.y2 <= 0 &&
					!item.status.lock &&
					!item.status.hide
				) {
					$store.chart.setTargetSelectChart(item.id, true);
				}
			}
		});
	}, 30);

	// 鼠标抬起
	const mouseup = () => {
		// 鼠标抬起时，结束mousemove的节流函数，避免选框不消失问题
		mousemove.cancel();
		$store.chart.setEditCanvas('isSelect', false);
		$store.chart.setMousePosition(0, 0, 0, 0);
		document.removeEventListener('mousemove', mousemove);
		document.removeEventListener('mouseup', mouseup);
	};
	document.addEventListener('mousemove', mousemove);
	document.addEventListener('mouseup', mouseup);
};

// * 鼠标事件
export const useMouseHandle = () => {
	// *  Click 事件, 松开鼠标触发
	const mouseClickHandle = (e, item) => {
		e.preventDefault();
		e.stopPropagation();
		if (item.status.lock) return;
		// 若此时按下了 CTRL, 表示多选
		if ($store.chart.KeyboardActive.ctrl) {
			// 若已选中，则去除
			if ($store.chart.targetChart.selectId.includes(item.id)) {
				const exList = $store.chart.targetChart.selectId.filter((e) => e !== item.id);
				$store.chart.setTargetSelectChart(exList);
			} else {
				$store.chart.setTargetSelectChart(item.id, true);
			}
		}
	};

	// * 按下事件（包含移动事件）
	const mousedownHandle = (e, item) => {
		e.preventDefault();
		e.stopPropagation();
		if (item.status.lock) return;
		// 按下左键 + CTRL
		if (e.buttons === 1 && $store.chart.KeyboardActive?.ctrl) return;

		// 按下右键 + 选中多个 + 目标元素是多选子元素
		const selectId = $store.chart.targetChart.selectId;
		if (e.buttons === 2 && selectId.length > 1 && selectId.includes(item.id)) return;

		// 选中当前目标组件
		$store.chart.setTargetSelectChart(item.id);

		// 按下右键
		if (e.buttons === 2) return;

		const scale = $store.chart.editCanvas.scale;
		const canvasWidth = $store.chart.editCanvasConfig.width;
		const canvasHeight = $store.chart.editCanvasConfig.height;

		// 记录图表初始位置和大小
		const targetMap = new Map();
		$store.chart.targetChart.selectId.forEach((id) => {
			const index = $store.chart.fetchTargetIndex(id);
			if (index !== -1) {
				const { x, y, w, h } = toRaw($store.chart.componentList[index]).orgConfig.attr;
				targetMap.set(id, { x, y, w, h });
			}
		});

		// 记录点击初始位置
		const startX = e.screenX;
		const startY = e.screenY;

		// 记录历史位置
		let prevComponentInstance = [];
		$store.chart.targetChart.selectId.forEach((id) => {
			if (!targetMap.has(id)) return;

			const index = $store.chart.fetchTargetIndex(id);
			// 拿到初始位置数据
			prevComponentInstance.push(cloneDeep($store.chart.componentList[index]));
		});

		// 记录初始位置
		$store.chart.setMousePosition(undefined, undefined, startX, startY);

		// 移动-计算偏移量
		const mousemove = throttle((moveEvent) => {
			$store.chart.setEditCanvas('isDrag', true);
			$store.chart.setMousePosition(moveEvent.screenX, moveEvent.screenY);

			// 当前偏移量，处理 scale 比例问题
			let offsetX = (moveEvent.screenX - startX) / scale;
			let offsetY = (moveEvent.screenY - startY) / scale;

			$store.chart.targetChart.selectId.forEach((id) => {
				if (!targetMap.has(id)) return;

				const index = $store.chart.fetchTargetIndex(id);
				// 拿到初始位置数据
				const { x, y, w, h } = targetMap.get(id);
				const componentInstance = $store.chart.componentList[index];

				let currX = Math.round(x + offsetX);
				let currY = Math.round(y + offsetY);

				// 基于左上角位置检测
				currX = currX < 0 ? 0 : currX;
				currY = currY < 0 ? 0 : currY;

				// 基于右下角位置检测
				currX = currX > canvasWidth - w ? canvasWidth - w : currX;
				currY = currY > canvasHeight - h ? canvasHeight - h : currY;

				if (componentInstance) {
					componentInstance.orgConfig.attr = Object.assign(componentInstance.orgConfig.attr, {
						x: currX,
						y: currY
					});
				}
			});
			return;
		}, 20);

		const mouseup = () => {
			try {
				$store.chart.setMousePosition(0, 0, 0, 0);
				$store.chart.setEditCanvas('isDrag', false);
				// 加入历史栈
				if (prevComponentInstance.length) {
					$store.chart.targetChart.selectId.forEach((id) => {
						if (!targetMap.has(id)) return;
						const index = $store.chart.fetchTargetIndex(id);
						const curComponentInstance = $store.chart.componentList[index];
						// 找到记录的所选组件
						prevComponentInstance.forEach((preItem) => {
							if (preItem.id === id) {
								preItem.orgConfig.attr = Object.assign(preItem.orgConfig.attr, {
									offsetX: curComponentInstance.orgConfig.attr.x - preItem.orgConfig.attr.x,
									offsetY: curComponentInstance.orgConfig.attr.y - preItem.orgConfig.attr.y
								});
							}
						});
					});
					$store.chart.moveComponentList(prevComponentInstance);
				}
				document.removeEventListener('mousemove', mousemove);
				document.removeEventListener('mouseup', mouseup);
			} catch (err) {
				console.log(err);
			}
		};

		document.addEventListener('mousemove', mousemove);
		document.addEventListener('mouseup', mouseup);
	};

	// * 进入事件
	const mouseenterHandle = (e, item) => {
		e.preventDefault();
		e.stopPropagation();
		if (!$store.chart.editCanvas.isSelect) {
			$store.chart.setTargetHoverChart(item.id);
		}
	};

	// * 移出事件
	const mouseleaveHandle = (e) => {
		e.preventDefault();
		e.stopPropagation();
		$store.chart.setEditCanvas('isDrag', false);
		$store.chart.setTargetHoverChart(undefined);
	};

	return { mouseClickHandle, mousedownHandle, mouseenterHandle, mouseleaveHandle };
};

// * 移动锚点
export const useMousePointHandle = (e, point, attr) => {
	e.stopPropagation();
	e.preventDefault();

	// 设置拖拽状态
	$store.chart.setEditCanvas('isDrag', true);
	const scale = $store.chart.editCanvas.scale;

	const itemAttrX = attr.x;
	const itemAttrY = attr.y;
	const itemAttrW = attr.w;
	const itemAttrH = attr.h;

	// 记录点击初始位置
	const startX = e.screenX;
	const startY = e.screenY;

	// 记录初始位置
	$store.chart.setMousePosition(startX, startY);

	const mousemove = throttle((moveEvent) => {
		$store.chart.setMousePosition(moveEvent.screenX, moveEvent.screenY);

		let currX = Math.round((moveEvent.screenX - startX) / scale);
		let currY = Math.round((moveEvent.screenY - startY) / scale);

		const isTop = /t/.test(point);
		const isBottom = /b/.test(point);
		const isLeft = /l/.test(point);
		const isRight = /r/.test(point);

		const newHeight = itemAttrH + (isTop ? -currY : isBottom ? currY : 0);
		const newWidth = itemAttrW + (isLeft ? -currX : isRight ? currX : 0);

		attr.h = newHeight > 0 ? newHeight : 0;
		attr.w = newWidth > 0 ? newWidth : 0;
		attr.x = itemAttrX + (isLeft ? currX : 0);
		attr.y = itemAttrY + (isTop ? currY : 0);
	}, 50);

	const mouseup = () => {
		$store.chart.setEditCanvas('isDrag', false);
		$store.chart.setMousePosition(0, 0, 0, 0);
		document.removeEventListener('mousemove', mousemove);
		document.removeEventListener('mouseup', mouseup);
	};

	document.addEventListener('mousemove', mousemove);
	document.addEventListener('mouseup', mouseup);
};
